﻿using System;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenCube.IO
{
	/// <summary>
	/// Factory for creating binairy readers from big- or little-endian streams.
	/// </summary>
	[ContractClass(typeof(BinaryReaderFactoryContracts))]
	[CLSCompliant(false)]
	public interface IBinaryReaderFactory
	{
		/// <summary>
		/// Create a reader that will read numbers from the given stream, based on the endianness of the stream.
		/// </summary>
		/// <param name="stream">The stream to tead the big- or little endian numbers from.</param>
		/// <param name="streamEndianness">The endianness of the stream to read from.</param>
		/// <returns>The created <see cref="IBinaryReader"/> that will read from the given stream.</returns>
		IBinaryReader CreateBinaryReader(Stream stream, Endianness streamEndianness);
	}

	/// <summary>
	/// Code Contracts for the <see cref="IBinaryReaderFactory"/> interface.
	/// </summary>
	[ContractClassFor(typeof(IBinaryReaderFactory))]
	abstract class BinaryReaderFactoryContracts
		: IBinaryReaderFactory
	{
		public IBinaryReader CreateBinaryReader(Stream stream, Endianness streamEndianness)
		{
			Contract.Requires<ArgumentNullException>(stream != null, "A stream is required");
			Contract.Requires<ArgumentOutOfRangeException>(Enum.IsDefined(typeof(Endianness), streamEndianness), "The given endianness is not understood or supported.");
			Contract.Requires<ArgumentOutOfRangeException>(streamEndianness != Endianness.None, "An endianness must be given");
			Contract.Requires<InvalidOperationException>(stream.CanRead, "The stream should be readable");
			Contract.Ensures(Contract.Result<IBinaryReader>() != null);
			throw new NotImplementedException();
		}
	}

}
